﻿using System;
using System.IO;
using System.Net;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.Practices.EnterpriseLibrary.Validation.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
using mki.Backup.Helper;

namespace mki.Backup.Objects.Helper
{
	/// <summary>
	/// Validates if a <see cref="T:System.String"/> is null or empty
	/// </summary>
	/// <remarks>
	/// Depends on: Microsoft.Practices.EnterpriseLibrary.Validation
	/// <list type="bullet">
	///		<item>You will need to reference following libraries
	///			<list type="bullet">
	///				<item>Microsoft.Practices.EnterpriseLibrary.Validation.dll</item>
	///				<item>Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WinForms.dll</item>
	///				<item>Microsoft.Practices.EnterpriseLibrary.Common.dll</item>
	///			</list>
	///		</item>
	/// </list>
	/// </remarks>
	[ConfigurationElementType(typeof(CustomValidatorData))]
	public class FTPConnectionValidator : Validator
	{
		#region Constructors (2)

		/// <summary>
		/// Initializes a new instance of the <see cref="FTPConnectionValidator"/> class.
		/// </summary>
		/// <param name="items">The items.</param>
		public FTPConnectionValidator(System.Collections.Specialized.NameValueCollection items) : base(null, null) { }

		/// <summary>
		/// Initializes a new instance of the <see cref="FTPConnectionValidator"/> class.
		/// </summary>
		public FTPConnectionValidator() : base(null, null) { }

		#endregion Constructors

		#region Properties (1)

		// Protected Properties (1) 

		/// <summary>
		/// Gets the message template to use when logging results no message is supplied.
		/// </summary>
		/// <value></value>
		protected override String DefaultMessageTemplate
		{
			get { return "The String '{0}' is NULL or empty"; }
		}

		#endregion Properties

		#region Methods (1)

		// Protected Methods (1) 

		/// <summary>
		/// Implements the validation logic for the receiver.
		/// </summary>
		/// <param name="objectToValidate">The object to validate.</param>
		/// <param name="currentTarget">The object on the behalf of which the validation is performed.</param>
		/// <param name="key">The key that identifies the source of <paramref name="objectToValidate"/>.</param>
		/// <param name="validationResults">The validation results to which the outcome of the validation should be stored.</param>
		/// <remarks>
		/// Subclasses must provide a concrete implementation the validation logic.
		/// </remarks>
		protected override void DoValidate(Object objectToValidate, Object currentTarget, String key, ValidationResults validationResults)
		{
			var isValid = false;
			var ftpJob = objectToValidate as FTPJobElement;

			if (ftpJob != null)
			{
				try
				{
					if (!String.IsNullOrWhiteSpace(ftpJob.FTPHost) && !String.IsNullOrWhiteSpace(ftpJob.RootFolder))
					{
						var uri = new Uri(Path.Combine(ftpJob.FTPHost, ftpJob.RootFolder).Replace(@"\", "/"));

						if (uri.Scheme == Uri.UriSchemeFtp)
						{
							// now try to connect
							var ftpWebRequest = WebRequest.Create(uri) as FtpWebRequest;
							if (ftpWebRequest == null) { return; }
							ftpWebRequest.Method = WebRequestMethods.Ftp.PrintWorkingDirectory;

							// user and password?
							if (!String.IsNullOrWhiteSpace(ftpJob.UserName) && !String.IsNullOrWhiteSpace(ftpJob.Password)) { ftpWebRequest.Credentials = new NetworkCredential(ftpJob.UserName, ftpJob.Password); }

							// delete file
							using (var response = ftpWebRequest.GetResponse() as FtpWebResponse)
							{
								isValid = response != null;
							}
						}
					}
				}
				catch (Exception ex)
				{
					Logging.WriteWarning("Error while validating FTP connection: {0}\n{1}", ex.Message, ex.StackTrace);
					isValid = false;
				}
			}

			if (isValid) { return; }

			var message = String.Format(MessageTemplate, key);
			LogValidationResult(validationResults, message, currentTarget, key);
		}

		#endregion Methods
	}

	/// <summary>
	/// 
	/// </summary>
	/// <exclude />
	public class FTPConnectionValidatorAttribute : ValidatorAttribute
	{
		#region Methods (1)

		// Protected Methods (1) 

		/// <summary>
		/// Creates the <see cref="T:Microsoft.Practices.EnterpriseLibrary.Validation.Validator"/> described by the attribute object providing validator specific
		/// information.
		/// </summary>
		/// <param name="targetType">The type of object that will be validated by the validator.</param>
		/// <returns>
		/// The created <see cref="T:Microsoft.Practices.EnterpriseLibrary.Validation.Validator"/>.
		/// </returns>
		/// <remarks>This operation must be overriden by subclasses.</remarks>
		protected override Validator DoCreateValidator(Type targetType)
		{
			return new FTPConnectionValidator();
		}

		#endregion Methods
	}
}